package com.genreate.util.words;

import cn.hutool.db.Entity;
import cn.hutool.db.nosql.redis.RedisDS;
import cn.hutool.json.JSONUtil;
import com.genreate.util.dbUtil.DbUtil;
import com.genreate.util.dbUtil.JdbcConfig;
import redis.clients.jedis.Jedis;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 敏感词过滤器
 *
 * @author LYS
 * @date 2024-12-17
 */
public class SensitiveWordFilter {
    public static Jedis jedis = RedisDS.create().getJedis();

    /**
     * 定义 Trie 树的根节点
     */
    private TrieNode root = new TrieNode();

    /**
     * 提供全局访问的单例
     */
    private static volatile SensitiveWordFilter INSTANCE = new SensitiveWordFilter();

    /**
     * 更新树结构
     */
    public static void updateInstanceRoot(){
        String redisKey = "sensitiveWords";
        List<String> wordsCache = null;
        String redisData = jedis.get(redisKey);
        if(redisData == null){
            DbUtil.setJdbcConfig(JdbcConfig.xinyuanForum());
            List<Entity> list = DbUtil.querys("select word from forum_sensitive_words_copy");
            wordsCache = list.stream().map(e->e.getStr("word")).collect(Collectors.toList());
            jedis.set(redisKey, JSONUtil.toJsonStr(wordsCache));
        }else {
            wordsCache = JSONUtil.toList(redisData,String.class);
        }
        SensitiveWordFilter instance = getInstance();
        instance.root = new TrieNode();
        for (String word : wordsCache) {
            instance.addWord(word);
        }
    }

    /**
     * 获取实例
     *
     * @return 敏感词过滤器
     */
    public static SensitiveWordFilter getInstance() {
        if (INSTANCE == null) {
            synchronized (SensitiveWordFilter.class) {
                if (INSTANCE == null) {
                    INSTANCE = new SensitiveWordFilter();
                }
            }
        }
        return INSTANCE;
    }

    /**
     * 构建 Trie 树
     *
     * @param word 词语
     */
    public void addWord(String word) {
        // 从根节点开始
        TrieNode current = root;
        // 遍历字符串中的每个字符
        for (char c : word.toCharArray()) {
            // 如果当前字符不在子节点中，则创建一个新的子节点
            current = current.children.computeIfAbsent(c, k -> new TrieNode());
        }
        // 将当前节点标记为单词的结尾
        current.isEnd = true;
    }

    /**
     * 检查文本 是否含敏感词
     *
     * @param text 文本
     * @return boolean
     */
    public boolean containsSensitiveWord(String text) {
        // 遍历文本中的每个字符
        for (int i = 0; i < text.length(); i++) {
            // 从根节点开始
            TrieNode current = root;
            // 遍历文本中的每个字符
            for (int j = i; j < text.length(); j++) {
                char c = text.charAt(j);
                // 如果当前字符不在子节点中，则跳出循环
                current = current.children.get(c);
                if (current == null) {
                    break;
                }
                // 如果当前节点是单词的结尾，则返回 true
                if (current.isEnd) {
                    return true;
                }
            }
        }
        // 如果没有找到敏感词，则返回 false
        return false;
    }


    /**
     * 查找并返回所有匹配到的敏感词
     *
     * @param text 文本
     */
    public Set<String> findSensitiveWords(String text) {
        Set<String> result = new HashSet<>();
        for (int i = 0; i < text.length(); i++) {
            TrieNode current = root;
            StringBuilder matchedWord = new StringBuilder();
            for (int j = i; j < text.length(); j++) {
                char c = text.charAt(j);
                current = current.children.get(c);
                if (current == null) {
                    break;
                }
                matchedWord.append(c);
                if (current.isEnd) {
                    result.add(matchedWord.toString());
                }
            }
        }
        return result;
    }

    /**
     * 定义 Trie 树的节点
     *
     * @author LYS
     * @date 2024-12-17
     */
    private static class TrieNode {
        // 子节点
        Map<Character, TrieNode> children = new HashMap<>();
        // 是否是单词的结尾
        boolean isEnd = false;
    }

    /**
     * 替换文本中的敏感词为 *
     *
     * @param text 文本
     * @return 替换后的文本
     */
    public String replaceSensitiveWords(String text) {
        StringBuilder result = new StringBuilder(text);
        for (int i = 0; i < text.length(); i++) {
            TrieNode current = root;
            int start = -1;
            for (int j = i; j < text.length(); j++) {
                char c = text.charAt(j);
                current = current.children.get(c);
                if (current == null) {
                    break;
                }
                if (current.isEnd) {
                    if (start == -1) {
                        // 记录敏感词开始位置
                        start = i;
                    }
                    // 敏感词长度
                    int length = j - i + 1;
                    for (int k = 0; k < length; k++) {
                        // 替换为 *
                        result.setCharAt(start + k, '*');
                    }
                    // 跳到敏感词结尾位置
                    i = j;
                    break;
                }
            }
        }
        return result.toString();
    }


    public static void main(String[] args) {
        String dataCode = "XZ001";
        String numStr = dataCode.substring("XZ".length());
        System.out.println(numStr);
    }
}